package com.putao.web.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.putao.annotation.OperateMethodName;
import com.putao.base.BaseController;
import com.putao.constants.Constants;
import com.putao.domain.Bill;
import com.putao.result.JsonResult;
import com.putao.service.BillService;
import com.putao.utils.RequestUtils;
import com.putao.utils.StringUtils;
import com.putao.utils.ThreadLocalUtil;
import com.putao.vo.BaseVo;
import com.putao.vo.BillVo;
import com.putao.web.controller.vo.bill.BillDataVo;
import com.putao.web.controller.vo.bill.BillOtherVo;
import com.putao.web.controller.vo.bill.BillResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author fuhehuang
 * @email 2628279194@qq.com
 */
@Api(tags = {"12.0 账单增删改查类"})
@RestController
@RequestMapping("/bills")
@Slf4j
public class BillController extends BaseController<Bill> {

    @Autowired
    private BillService billService;

    /**
     * 账单列表
     *
     * @return
     */
    @GetMapping
//    @RequiresRoles(value={"admin"})
    @ApiOperation(value = "账单列表", notes = "base对象")
    @OperateMethodName(value = "账单列表", method = "bill:list")
    public JsonResult list(HttpServletRequest request, BaseVo baseVo) {
        String env = RequestUtils.getEnv(request);
        String userId = ThreadLocalUtil.getUserId();
        if (BaseVo.ENV_PHONE.equals(env)) {
            return getBillListForPhone(baseVo, userId);
        }
        PageHelper.startPage(baseVo.getPageIndex(), baseVo.getPageSize());
        QueryWrapper<Bill> wrapper = createWrapper();
        wrapper.like(Strings.isNotBlank(baseVo.getSearch()), "billname", baseVo.getSearch());
        wrapper.eq(StringUtils.isNotBlank(baseVo.getColumnName())
                && StringUtils.isNotBlank(baseVo.getSelect()), baseVo.getColumnName(), baseVo.getSelect());
        orderByModifyTimeDesc(wrapper);
        List<Bill> list = billService.list(wrapper);
        return selectNotFound(new ArrayList<>(), 0);
    }

    private JsonResult getBillListForPhone(BaseVo baseVo, String userId) {
        // 默认开始查询第一个账本的，然后查询出每个账本下所有的账单，按照月分组，然后按照天分组。并统计全部的数据，收入，支出，结余。默认查询的年份是当前年，没有传参数时
        QueryWrapper<Bill> wrapper = createWrapperWithUserId(userId);
        wrapper.eq(StringUtils.isNotBlank(baseVo.getParentId()), "account_book_id", baseVo.getParentId()).eq(StringUtils.isNotBlank(baseVo.getYear()), "year(create_time)", baseVo.getYear());
        List<Bill> billList = billService.selectListByPhone(baseVo, userId, wrapper);
        BillResultVo billResultVo = new BillResultVo();
        if (CollectionUtil.isNotEmpty(billList)) {
            // 计算支出
            BigDecimal pay = billList.stream().filter(bill -> Constants.BILL_TYPE_PAY.equals(bill.getType())).map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            billResultVo.setPayMoney(pay);
            // 计算收入
            BigDecimal income = billList.stream().filter(bill -> Constants.BILL_TYPE_INCOME.equals(bill.getType())).map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            billResultVo.setIncomeMoney(income);
            // 计算余额
            billResultVo.setBalances(income.subtract(pay));
            // 根据月分组
            Map<String, List<Bill>> monthBillListMap = billList.stream().collect(Collectors.groupingBy(Bill::getMonthStr));
            Map<String, BillOtherVo> billOtherVoMap = new HashMap<>();
            for (String month : monthBillListMap.keySet()) {
                BillOtherVo billOtherVo = new BillOtherVo();
                billOtherVo.setMonth(month);
                // 一个月的账单
                List<Bill> bills = monthBillListMap.get(month);
                if (CollectionUtil.isNotEmpty(bills)) {
                    billOtherVo.setIncome(bills.stream().filter(bill -> Constants.BILL_TYPE_INCOME.equals(bill.getType())).map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
                    billOtherVo.setPay(bills.stream().filter(bill -> Constants.BILL_TYPE_PAY.equals(bill.getType())).map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
                    // 按照天分组
                    Map<String, List<Bill>> dayBillListMap = bills.stream().collect(Collectors.groupingBy(Bill::getDayTime));
                    List<BillDataVo> billDataVoList = new ArrayList<>();
                    for (String day : dayBillListMap.keySet()) {
                        BillDataVo billDataVo = new BillDataVo();
                        List<Bill> billList1 = dayBillListMap.get(day);
                        billDataVo.setBillList(billList1);
                        billDataVo.setDayTimeStr(day);
                        if (CollectionUtil.isNotEmpty(billList1)) {
                            billDataVo.setDayForWeek(billList1.get(0).getWeekStr());
                        }
                        Map<String, List<Bill>> typeBillListMap = billList1.stream().collect(Collectors.groupingBy(Bill::getType));
                        List<Bill> incomeBillList = typeBillListMap.get(Constants.BILL_TYPE_INCOME);
                        if (CollectionUtil.isNotEmpty(incomeBillList)) {
                            billDataVo.setIncomeMoney(incomeBillList.stream().map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
                        }
                        List<Bill> payBillList = typeBillListMap.get(Constants.BILL_TYPE_PAY);
                        if (CollectionUtil.isNotEmpty(payBillList)) {
                            billDataVo.setPayMoney(payBillList.stream().map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
                        }
                        billDataVoList.add(billDataVo);
                    }
                    billOtherVo.setBillDataVoList(billDataVoList);
                }
                billOtherVoMap.put(month, billOtherVo);
            }
            billResultVo.setYearBillOtherVoMap(billOtherVoMap);
            return JsonResult.selectSuccess(billResultVo, 0);
        }
        return JsonResult.selectNotFound(billResultVo, 0);
    }

    @PutMapping
    @ApiOperation(value = "账单修改", notes = "路径参数传入账单对象")
    @OperateMethodName(value = "账单修改", method = "bill:update")
    public JsonResult update(@RequestBody BillVo billVo){
        if (!Strings.isNotBlank(billVo.getId())){
            return updateNotFound(billVo, null);
        }
        Bill bill = billService.updateBill(billVo);
        return updateSuccess(bill, null);
    }


    @PostMapping
    @ApiOperation(value = "添加账单", notes = "添加账单")
    @OperateMethodName(value = "添加账单", method = "bill:insert")
    public JsonResult insert(@RequestBody BillVo billVO){
        Bill bill = billService.saveBill(billVO);
        return insertSuccess(null, billVO);
    }

    @DeleteMapping
    @ApiOperation(value = "删除", notes = "参数传入id")
    @OperateMethodName(value = "账单删除,批量", method = "bill:delete")
    public JsonResult delete(String id){
        return this.delete(id, billService, bill -> billService.afterUpdateBill(bill));
    }
}
